package com.zhangkeyou.map.mapweb.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhangkeyou.map.mapweb.domain.entity.Feature;
import com.zhangkeyou.map.mapweb.domain.entity.Features;
import com.zhangkeyou.map.mapweb.domain.entity.Status;
import com.zhangkeyou.map.mapweb.exception.DefinitionException;
import com.zhangkeyou.map.mapweb.mapper.FeaturesMapper;
import com.zhangkeyou.map.mapweb.util.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FeaturesService {
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FeaturesMapper featuresMapper;


    public FeaturesService(FeaturesMapper featuresMapper,RedisCache redisCache) {
        this.featuresMapper = featuresMapper;
        this.redisCache = redisCache;
        updateTempFeaturesList(false);
    }

    private void updateTempFeaturesList(boolean reloadFromDatabase){
        String featureListInRedis = "featureList";
        List<Features> featuresList = null;
        if(reloadFromDatabase){
            int level = 1;
            featuresList = getFeatureList2(1,null);
/*            featuresList = featuresMapper.getFeaturesListByLevelAndParentId(level,null);
            featuresList.forEach(features ->
                    getFeatureList(level+1,features)
            );*/
            log.debug("加载已地图列表");
            redisCache.setCacheObject(featureListInRedis,featuresList);
            tempFeaturesList = featuresList;
        }else{
//        if(false){//redis 无法保存
            featuresList = redisCache.getCacheObject(featureListInRedis);
            if(!Objects.isNull(featuresList)){
                log.debug("从redis中加载已地图列表");
                tempFeaturesList = featuresList;
            }
        }
        return;
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesService.class);
    public Status getFeaturesInfo(int level,String parentId){
        Status status = new Status();
        try{
            if(level>1&&parentId==null){
                status.setState(400);
                status.setMsg("缺少参数");
            }else{
                Features featuresInfo = featuresMapper.getFeaturesInfo(level, parentId);
                status.setData(featuresInfo);
                status.setState(200);
            }
        }catch (Exception ex){
            LOGGER.debug(Arrays.toString(ex.getStackTrace()));
            status.setState(400);
            status.setMsg(ex.getMessage());
        }
        return status;
    }

    public Feature getFeatureByFeatureId(String featureId){
        Feature feature = featuresMapper.getFeatureWithGeometryByFeatureId(featureId);
        if(Objects.isNull(feature)){
            throw new DefinitionException(403,"Not found");
        }
        return feature;
    }

    private static List<Features> tempFeaturesList = null;

    public List<Features> getFeatureList() {
        //todo 多线程
        if(tempFeaturesList==null){
            updateTempFeaturesList(false);
        }
        return tempFeaturesList;
    }

    @Async("myExecutor")
    public void getFeatureList(int level, Features features){
        List<Feature> featureList = features.getFeatures();
        for (Feature feature : featureList) {
            List<Features> featuresList = featuresMapper.getFeaturesListByLevelAndParentId(level, feature.getId());
//            System.out.println(i);
            if (featuresList != null && featuresList.size() > 0) {
                Features fs = featuresList.get(0);
                feature.setChildrenFeatures(fs);
//                if (level + 1 < 4)
                getFeatureList(level + 1, fs);
            }
        }

        /*features.getFeatures().forEach(feature -> {
            List<Features> featuresList = featuresMapper.getFeaturesList(level, feature.getId());
            System.out.println(date);
            if(featuresList!=null&&featuresList.size()>0){
                Features fs = featuresList.get(0);
                feature.setChildrenFeatures(fs);
                if(level+1<4)
                    getFeatureList(level+1,fs,new Date());
            }
        });*/
    }


    public List<Features> getFeatureList2(int level, Feature feature){
        List<Features> firstLevelFeaturesList;
        if(level<=0){
            throw new RuntimeException("level 值非法");
        }
        if(level==1){
            firstLevelFeaturesList = featuresMapper.getFeaturesListByLevelAndParentId(1,null);
        }else{
            if(Objects.isNull(feature)){
                throw new RuntimeException("feature不能为空");
            }
            firstLevelFeaturesList = featuresMapper.getFeaturesListByLevelAndParentId(level, feature.getId());
        }
        firstLevelFeaturesList.forEach(firstLevelFeatures->{
            List<Feature> firstLevelFeatureList = firstLevelFeatures.getFeatures();
            firstLevelFeatureList.forEach(firstLevelFeature->{
                List<Features> childrenFeatures = getFeatureList2(level+1,firstLevelFeature);
                if(childrenFeatures!=null&&childrenFeatures.size()>0) {
                    firstLevelFeature.setChildrenFeatures(childrenFeatures.get(0));
                }
            });
        });
        return firstLevelFeaturesList;
    }


    public void insertFeatures(Features featuresNeedInsert){
        Features featuresInDatabase = featuresMapper.selectByFeaturesNameAndLevel(featuresNeedInsert);
        log.info(String.format("insert features :-->%s",featuresNeedInsert.toString()));
        if(featuresInDatabase!=null){
            //更新已有数据
            featuresMapper.updateFeaturesByFeaturesId(featuresNeedInsert,featuresInDatabase.getId());
            Map<String, String> feature_Id_FeatureId_InDatabase_Map = featuresInDatabase.getFeatures().stream()
                    .collect(Collectors.toMap(Feature::getId, Feature::getFeatureId));
            featuresNeedInsert.getFeatures().forEach(featureInsert -> {
                String featureId = feature_Id_FeatureId_InDatabase_Map.get(featureInsert.getId());
                if(featureId!=null){
                    featuresMapper.updateFeatureByFeatureId(featureInsert,featureId);
                }else{
                    featureInsert.setFeaturesId(featuresInDatabase.getId());
                    featuresMapper.insertFeature(featureInsert);
                }
            });
        }
        else{
            //插入新数据
            featuresMapper.insertFeatures(featuresNeedInsert);
            featuresNeedInsert.getFeatures().forEach(item->{
                featuresMapper.insertFeature(item);
            });
        }
        updateTempFeaturesList(true);
    }

    public Feature getFeatureByLevelId(int level, String parentId) {
        List<Feature> features = featuresMapper.getFeatureByLevelId(level,parentId);
        if(features!=null&&features.size()>0){
            return features.get(0);
        }else{
            return null;
        }
    }


    /**
     * 简单的将json数据转为Features
     * @param file
     * @return
     * @throws IOException
     */
    private Features multipartFileToFeatures(MultipartFile file) throws IOException {
        InputStream inputStream1 = file.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream1, "UTF-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
            }

            Features features = JSON.parseObject(sb.toString(), Features.class);
            return features;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                inputStream1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        /*InputStream inputStream = null;
        try{
            inputStream = file.getInputStream();
            StringBuilder builder = new StringBuilder();
            byte[] buffer = new byte[1000];
            int n;
            while ((n = inputStream.read(buffer)) != -1) { // 读取到缓冲区
                builder.append(new String(buffer,0,n));
            }
            Features features = JSON.parseObject(builder.toString(), Features.class);
//        features.setFeaturesName("省界");
//        features.setLevel();
            return features;
        }catch (Exception ex){
            log.error("更新地图失败："+ex.getMessage());
            return null;
        }finally {
            if(inputStream!=null){
                inputStream.close();
            }
        }*/
    }

    /**
     * 通过parentId和level获取FeatureList
     * @param level
     * @param parentId
     * @return
     */
    public List<Feature> getFeatureListByLevelParentId(int level, String parentId) {
        List<Feature> featuresList = featuresMapper.getFeatureListByLevelAndParentId(level, parentId);
        if(Objects.isNull(featuresList))
            throw new DefinitionException(403,"未找到数据parentId："+parentId+"level="+level+"的Feature");
        return featuresList;
    }

    public List<Features> getFirstLevelFeatures() {
        List<Features> featuresList = featuresMapper.getFirstLevelFeatures();
        if (Objects.isNull(featuresList)){
            throw new DefinitionException(403,"未找到第一层数据");
        }
        return featuresList;
    }

    /**
     * 通过level和FeaturesId获取Feature
     * @param level
     * @param featuresId
     * @return
     */
    public List<Feature> getFeatureListByLevelAndFeaturesId(int level, String featuresId) {
        List<Feature> featureList = featuresMapper.getFeatureListByLevelAndFeaturesId(level,featuresId);
        if (Objects.isNull(featureList)) {
            throw new DefinitionException(403, "未找到数据featuresId：" + featuresId + "level=" + level + "的Feature");
        }
        return featureList;
    }



    public Features getFeaturesInfoByFile(MultipartFile file) {
        Features features = getFeaturesByFile(file);
        if(Objects.isNull(features)){
            throw new DefinitionException(400,"提取失败");
        }
        return features;
    }

    /**
     * 将json数据转为Features，并提取json中的attributes信息到Feature中
     * @param file
     * @return
     */
    public Features getFeaturesByFile(MultipartFile file) {
        String featuresName;
        String featureIdFieldName;
        String featureNameFieldName;
        int levelFieldName;
        String featureParentIdFieldName;
        Features features = null;
        /**
         * fileName = "县.县代码.县.3.市代码.json"
         * 县.               县代码.                县.                      3.      市代码.json
         * featuresName.    featureIdFieldName.     featureNameFieldName.   level.  featureParentIdFieldName.json
         *
         * 1->featuresName Features 的Name
         * 2->featureIdFieldName feature的id字段
         * 3->featureNameFieldName feature的name字段                   ↓
         * 4->level 上传的地图的在第几层 level>0
         * 4->featureParentIdFieldName feature的父feature的id
         */

        String[] fileName = file.getOriginalFilename().split("\\.");
        if(fileName.length==6&&//文档名称符合要求
                fileName[fileName.length-1].equals("json")//文件为JSON
        ) {
            try {
                featuresName = fileName[0];
                featureIdFieldName = fileName[1];
                featureNameFieldName = fileName[2];
                levelFieldName = Integer.parseInt(fileName[3]);
                featureParentIdFieldName = fileName[4];

                if(levelFieldName>1&&featureIdFieldName!=null&&featureIdFieldName.equals("")){
                    throw new RuntimeException("level>1 但没有指定parentId");
                }
                // 粗提取，没有设计attributes
                features = multipartFileToFeatures(file);
                // 将attributes信息保存到Features中
                if(features!=null) {
                    features.setFeaturesName(featuresName);
                    features.setLevel(levelFieldName);
                    features.extractFeatureFromAttribute(featureIdFieldName,
                            featureParentIdFieldName,
                            featureNameFieldName);

                }
            } catch (Exception ex) {
                log.error(ex.toString());
                return null;
            }
        }
        return features;
    }

    public Object deleteByLevelAndId(int level, String id) {
        //todo 返回值重新编写
        List deleteObjects = new ArrayList();
        if(level==0){
            List<Feature> featureList = featuresMapper.getFeaturesListByFeaturesIdWithoutGeometry(id);
            featureList.forEach(feature -> {
                deleteFeature(feature,1);
            });
            if(featureList.size()>0) {
                int count = featuresMapper.deleteFeaturesById(id);
            }
        }else{
            Feature feature = featuresMapper.getFeatureByFeatureIdWithoutGeometry(id);
            deleteObjects = deleteFeature(feature,level);
        }
        deleteNullFeatures();
        updateTempFeaturesList(true);
        return null;
    }

    /**
     * 删除没有feature的Features
     */
    private void deleteNullFeatures(){
        List<String> featuresId = featuresMapper.getAllFeaturesId();
        featuresId.forEach(id->{
            int count = featuresMapper.getFeatureCountByFeaturesId(id);
            if(count==0){
                featuresMapper.deleteFeaturesById(id);
            }
        });
    }
    private List deleteFeature(Feature feature,int level) {
        List deleteFeature = new ArrayList<>();
        deleteFeature.add(feature);
        List<Feature> childrenFeatureList =
                featuresMapper.getFeatureListByLevelAndParentId(level+1, feature.getId());
        childrenFeatureList.forEach(childrenFeature->{
            List list = deleteFeature(childrenFeature, level + 1);
            deleteFeature.add(list);
        });
        int count = featuresMapper.deleteFeatureByFeatureId(feature.getFeatureId());
        return deleteFeature;
    }

    public Object updateFeatureByJson(JSONObject json) {
        Feature feature = JSON.parseObject(json.toJSONString(), Feature.class);
        featuresMapper.updateFeatureByFeatureId(feature, feature.getFeatureId());
        return null;
    }

    public Status updateFeaturesList() {
        updateTempFeaturesList(true);
        return null;
    }
/*
    @Async("myExecutor")
    public void executeAsyncTask(int i) {
        System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务：" + i);
    }*/
}
